/*
 * PassengerQueue.h
 *
 *  Created on: 26/04/2012
 *      Author: alex
 */

#ifndef PASSENGERQUEUE_H_
#define PASSENGERQUEUE_H_

#include <iostream>
#include "ElevatorPassenger.h"
#include "../common/Object.h"
#include "../IPC/NamedPipe.h"
#include "../IPC/Semaphore.h"

/**
 * Cola de pasajeros, para comunicarlos entre los distintos
 * procesos.
 */
class PassengerQueue: public Object
{
	static const int INITIAL_QUEUE_KEY=100;

public:
	typedef enum{PRODUCER_END=0, CONSUMER_END} EndTypeEnum;
public:
	/**
	 * Constructor
	 * @param filePath path que se usara para el archivo del mecanismo
	 * 					de IPC utilizado.
	 * @param type tipo de extremo de la Passenger (PRODUCER/CONSUMER)
	 */
	PassengerQueue(std::string filePath,std::string keyGeneratorPath,int queueId,EndTypeEnum type);

	/**
	 * Destructor
	 */
	virtual ~PassengerQueue();

	/**
	 * Crea el canal de comunicacion a utilizar.
	 * Solo es necesario hacer una vez por canal.
	 * Luego de este metodo aun es necesario llamar a open()
	 * para poder utilizar el canal.
	 */
	void create();

	/**
	 * Abre el mecanismo de comunicacion subyacente, dejandolo listo
	 * para leer/escribir.
	 * Se debe haber llamado a create() para crear el canal de comunicacion
	 * previamente.
	 */
	void open();

	/**
	 * Cierra el canal de comunicacion.
	 */
	void close();

	/**
	 * Elimina el mecanismo del canal de comunicacion, solo es necesario
	 * hacer una vez luego de terminar de usar en todos los procesos,
	 * a fin de liberar recursos.
	 */
	void destroy();

	/**
	 * Inserta un pasajero en la queue. En caso que el canal de
	 * comunicacion este lleno se bloquea hasta poder insertar el pasajero.
	 * @param passenger Pasajero a insertar
	 */
	void pushPassenger(ElevatorPassenger &passenger);

	/**
	 * Obtiene un pasajero desde el canal de comunicacion.
	 * Si no hay ningun pasajero en el canal se bloquea hasta leer uno.
	 * @returns ElevatorPassenger Pasajero leido desde el canal.
	 */
	ElevatorPassenger *popPassenger();

	/**
	 * Obtiene un pasajero, sin removerlo del queue
	 * El obj devuelto debe ser liberado por el invocador.
	 * @param floorId id del piso por el cual se pregunta.
	 * @returns ElevatorPassenger * pasajero del ascensor.
	 */
	ElevatorPassenger *peekPassenger();

	/**
	 * Indica que el pasajero que se pidio anteriormente mediante
	 * un peek debe ser eliminado.
	 */
	void deletePeekedPassenger();

	/**
	 * Se fija si hay un pasajero en el canal, pero no es bloqueante.
	 * @returns bool true si hay pasajeros esperando, false en caso
	 * 			contrario.
	 */
	bool hasPassengers();

private:
	/**
	 * Pipe utilizado como mecanismo de comunicacion por la queue.
	 */
	NamedPipe *m_Pipe;

	/**
	 * Tipo de extremo de esta instancia de la queue (PRODUCER/CONSUMER)
	 */
	EndTypeEnum m_EndType;

	/**
	 *
	 */
	ElevatorPassenger *m_FirstPassenger;

	/**
	 *
	 */
	Semaphore m_semaphore;
};

#endif // PASSENGERQUEUE_H_
